#include "gamestate.h"

#include "gamewindow.h"
#include "window.h"
#include <QGridLayout>
#include "statemanager.h"
#include "gameapplication.h"
#include <QFile>
#include <QTextStream>

#include <statechangeevent.h>
#include <handsmoveevent.h>
#include <handgestureevent.h>

using namespace mlgesture;

GameState::GameState()
{
	gesture_ = NULL;
	window_ = new GameWindow();
	resultWindow_ = new resultWidget();
	connect(window_, SIGNAL(closeGame()), this, SLOT(returnMenu()));
	connect(window_, SIGNAL(emitScore(int)), resultWindow_, SLOT(setScore(int)));
	connect(window_, SIGNAL(emitPurpose(QString)), resultWindow_, SLOT(setPurpose(QString)));
	connect(window_, SIGNAL(endGame()), this, SLOT(endGame()));
	connect(resultWindow_, SIGNAL(returnMenu()), this, SLOT(returnMenu()));

	timer_ = new QTimer();
}

GameState::~GameState() {
	delete window_;
	gesture_->stopProcess();
	gesture_->releaseCamera();
	if (gesture_)
		delete gesture_;
}

void GameState::enter() {
	Window::getLayout()->addWidget(window_,1,1);
	window_->restart();
	window_->show();
	window_->setRunning(false);
	isShooting_ = false;
	resetParams();
	time_.start();
	isEnd_ = false;
	MLGesture::addObserver(this);
}

void GameState::exit() {
	MLGesture::removeObserver(this);
	if (isEnd_) {
		Window::getLayout()->removeWidget(resultWindow_);
		resultWindow_->hide();
	}
	else {
		timer_->stop();
		if (gesture_) {
			gesture_->stopProcess();
			gesture_->releaseCamera();
		}
		window_->hide();
		Window::getLayout()->removeWidget(window_);
	}
}

void GameState::returnMenu() {
	StateManager::getInstance().setState("menu");
}

void GameState::setParams(int cam_id, int low_skin, int upper_skin, int low_value, int upper_value,
						  bool adapt_algorithm, double tracking_sensity, bool show_camera_img, bool show_mask_img) {
	if (gesture_) {
		delete gesture_;
	}
	gesture_ = new MLGesture(cam_id, 2);
	if (low_skin >= 0 && upper_skin >= 0 && low_value >=0 && upper_value >=0){
		gesture_->adjustSkinFilter(low_skin, upper_skin, low_value, upper_value);
	}
	if (tracking_sensity >=0 && tracking_sensity <= 1) {
		gesture_->adjustTrackingSensity(tracking_sensity);
	}
	gesture_->setAdaptiveAlgoritm(adapt_algorithm);
	showCameraImg_ = show_camera_img;
	showMaskImg_ = show_mask_img;
	if (show_camera_img || show_mask_img) {
		window_->setWindowSize(960, 480);
	}
	else {
		window_->setWindowSize(640, 480);
	}
	window_->setSidePanel(show_camera_img, show_mask_img);
	connect(timer_, SIGNAL(timeout()), this, SLOT(process()));
	timer_->start(40);
	gesture_->enableStaticGesture(true);
	gesture_->loadStaticGesturesModels("models/static.dat.model", "models/static.dat.scale_factors", "models/label.dat");
	gesture_->startProcess();
}

void GameState::resetParams() {
	int low_h, upper_h, low_v, upper_v;
	GameApplication::getSkinThresholds(low_h, upper_h);
	GameApplication::getValueThreshold(low_v, upper_v);
	setParams(GameApplication::getCamIdSettings(), low_h, upper_h, low_v, upper_v, GameApplication::getAdaptThreshold(),
			  GameApplication::getTrackingSensity(),
			  GameApplication::getShowImageSettings(), GameApplication::getShowMaskSettings());
}

void GameState::process() {
	if (isShooting_) {
		window_->addBullet();
	}
	Mat frame, mask;
	gesture_->getFrame(frame);
	gesture_->getMask(mask);
	window_->setCameraTextures(frame, mask);
	window_->renderContext(time_.restart());
}

void GameState::endGame() {
	exit();
	Window::getLayout()->addWidget(resultWindow_,1,1);
	resultWindow_->show();
	isEnd_ = true;
}

void GameState::processEvent(GestureEvent *event) {
	StateChangeEvent *state_event;
	HandsMoveEvent *move_event;
	HandGestureEvent *static_event;
	switch(event->getType()) {
	case GestureEvent::STATE_EVENT:
		state_event = dynamic_cast<StateChangeEvent*>(event);
		window_->setRunning(state_event->getState());
		break;
	case GestureEvent::MOVE_EVENT:
		move_event = dynamic_cast<HandsMoveEvent*>(event);
		window_->setAngle(move_event->getAngle());
		break;
	case GestureEvent::STATIC_BEGIN_EVENT:
		static_event = dynamic_cast<HandGestureEvent*>(event);
		if (static_event->getHandId() == 1 && static_event->getGestureId() == 2) {
			isShooting_ = true;
		}
		break;
	case GestureEvent::STATIC_END_EVENT:
		static_event = dynamic_cast<HandGestureEvent*>(event);
		if (static_event->getHandId() == 1 && static_event->getGestureId() == 2) {
			isShooting_ = false;
		}
		break;
	default:
		break;
	}
}

